package ru.geyes.screw.tuples;

import ru.geyes.screw.utils.EqualsUtils;
import ru.geyes.screw.collections.*;
import ru.geyes.screw.closures.Function2V;
import ru.geyes.screw.closures.Function2P;
import ru.geyes.screw.closures.Function2B;
import ru.geyes.screw.closures.Function;

import java.util.*;

/**
 * @author alex
 * @date 31.05.2008
 */
public class Tuple2<A, B> implements MapX<A, B> {
    private final A a;
    private final B b;

    public Tuple2(A _0, B _1) {
        this.a = _0;
        this.b = _1;
    }

    public A _0() {
        return a;
    }

    public B _1() {
        return b;
    }

    public int size() {
        return 1;
    }

    public boolean isEmpty() {
        return false;
    }

    public boolean containsKey(Object o) {
        return EqualsUtils.isEquals(a, o);
    }

    public boolean containsValue(Object o) {
        return EqualsUtils.isEquals(b, o);
    }

    public B get(Object o) {
        return (EqualsUtils.isEquals(a, o))? b: null;
    }

    public B put(A a, B b) {
        throw new RuntimeException("Not implemented yet.");
    }

    public B remove(Object o) {
        throw new RuntimeException("Not implemented yet.");
    }

    public void putAll(Map<? extends A, ? extends B> map) {
        throw new RuntimeException("Not implemented yet.");
    }

    public void clear() {
        throw new RuntimeException("Not implemented yet.");
    }

    public Set<A> keySet() {
        HashSet<A> set = new HashSet<A>(1);
        set.add(a);
        return set;
    }

    public Collection<B> values() {
        List list = new ArrayList(1);
        list.add(b);
        return list;
    }

    public Set<Entry<A, B>> entrySet() {
        HashSet<Entry<A, B>> set = new HashSet<Entry<A, B>>(1);
        set.add(new AbstractMap.SimpleEntry<A,B>(a, b));
        return set;
    }

    public ListX<B> flatMap() {
        return ListXUtil.wrap(b);
    }

    public Option<B> getO(A key) {
        return (containsKey(key))? Option.option(b): Option.<B>none();
    }

    public ListX<B> valuesX() {
        return ListXUtil.wrap(b);
    }

    public void forAll(Function2V<A, B> exec) {
        exec.apply(a, b);
    }

    public <S> MapX<A, S> map(Function2P<S, A, B> mapper) {
        return MapXUtils.wrap(a, mapper.apply(a, b));
    }

    public MapX<A, B> filter(Function2B<A, B> filterF) {
        return (filterF.apply(a, b))? this: MapXUtils.<A, B>emptyMap();
    }

    public B getOrPut(A key, Function<B> closure) {
        throw new RuntimeException("Not implemented yet.");
    }
}
